package org.codingq92.frame.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.net.SocketAddress;

/**
 * 初始化并启动服务器，配置服务器的事件循环组、通道、以及通道初始化器
 *
 * @author: CodingQ92
 * @date: 2025/7/2 22:20
 */
public class NettyServer {

    public static void main(String[] args) {
        // 创建并配置服务器引导器
        ServerBootstrap serverBootstrap = new ServerBootstrap()
                // 设置两个事件循环组，分别用于服务器端和客户端
                .group(new NioEventLoopGroup(), new NioEventLoopGroup())
                // 指定使用NIO类型的服务器通道
                .channel(NioServerSocketChannel.class)
                // 设置通道初始化器，用于配置通道的处理器
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sChannel) throws Exception {
                        // 配置通道的处理管道
                        // 入站方向（客户端 → 服务端）
                        // 出站方向（服务端 → 客户端）
                        sChannel.pipeline()
                                // 入站处理器：将字节流按行分割（处理粘包/拆包）
                                .addLast(new LineBasedFrameDecoder(1024))
                                // 入站处理器：将字节转换为字符串
                                .addLast(new StringDecoder())
                                // 出站处理器：将字符串转换为字节
                                .addLast(new StringEncoder())
                                // 入站处理器：处理业务逻辑
                                .addLast(new SimpleChannelInboundHandler<String>() {
                                    @Override
                                    protected void channelRead0(ChannelHandlerContext chc, String s) {
                                        // 输出接收到的消息
                                        SocketAddress remoteAddress = chc.channel().remoteAddress();
                                        System.out.println("接受到客户端[" + remoteAddress + "]的消息：" + s);
                                        // 收到消息后回复客户端
                                        // 消息流向
                                        // 1.TailHandler（默认处理器，自动添加）：消息起点。
                                        // 2.StringEncoder(将 String 编码为 ByteBuf。)
                                        // 3.HeadHandler（默认处理器）：将 ByteBuf 写入底层 SocketChannel。
                                        // 4.网络
                                        chc.channel().writeAndFlush("已收到消息" + System.currentTimeMillis() + "\n");
                                        // 消息流向
                                        // 1.StringEncoder：编码 String 为 ByteBuf。
                                        // 2.HeadHandler（默认处理器）：将 ByteBuf 写入底层 SocketChannel。
                                        // 3.网络
                                        // chc.writeAndFlush("已收到消息" + System.currentTimeMillis());
                                    }
                                });
                    }
                });
        // 绑定端口
        ChannelFuture future = serverBootstrap.bind(18000);
        // 添加监听器，用于处理服务器启动成功后的操作
        future.addListener(future1 -> {
            if (future1.isSuccess()) {
                // 如果服务器成功启动，输出成功信息
                System.out.println("服务器启动成功,端口:" + 18000);
            }
        });
    }

}
